#!/bin/bash
# 配置文件语法错误修复工具
# 用法: ./fix_config_syntax.sh <配置文件路径>
FIX_CODE_ID="configerror"

# 检查参数是否提供
if [ $# -ne 1 ]; then
    echo "用法: $0 <配置文件路径>"
    exit 1
fi

CONFIG_FILE="$1"

# 配置参数
BACKUP_DIR="/var/backups/config_fix"  # 配置文件备份目录
LOG_FILE="/var/log/config_syntax_fix.log"
MAX_BACKUP_COUNT=5                   # 保留的最大备份数量
SYNTAX_CHECK_CMD=""                  # 语法检查命令，会根据文件类型自动设置
FIX_STRATEGY="auto"                  # 修复策略: auto/manual

# 日志函数
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

# 检查配置文件是否存在
check_file_exists() {
    if [ ! -f "$CONFIG_FILE" ]; then
        log "错误: 配置文件不存在 - $CONFIG_FILE"
        echo "错误: 配置文件不存在 - $CONFIG_FILE"
        return 1
    fi
    return 0
}

# 根据文件类型确定语法检查命令
determine_check_command() {
    local file_ext=$(echo "$CONFIG_FILE" | awk -F. '{print $NF}')
    local file_name=$(basename "$CONFIG_FILE")
    
    case "$file_name" in
        "my.cnf"|"mysql.cnf")
            SYNTAX_CHECK_CMD="mysqld --defaults-file=$CONFIG_FILE --help --verbose 2>&1"
            log "检测到MySQL配置文件，使用mysqld进行语法检查"
            ;;
        "nginx.conf")
            SYNTAX_CHECK_CMD="nginx -t -c $CONFIG_FILE 2>&1"
            log "检测到Nginx配置文件，使用nginx -t进行语法检查"
            ;;
        "httpd.conf"|"apache2.conf")
            SYNTAX_CHECK_CMD="apachectl -t -f $CONFIG_FILE 2>&1"
            log "检测到Apache配置文件，使用apachectl -t进行语法检查"
            ;;
        *)
            case "$file_ext" in
                "conf")
                    # 通用配置文件检查（使用grep查找明显错误）
                    SYNTAX_CHECK_CMD="grep -E '^[^#]*=[^=]+$' $CONFIG_FILE >/dev/null 2>&1"
                    log "检测到通用配置文件，使用基本语法检查"
                    ;;
                "json")
                    SYNTAX_CHECK_CMD="python3 -m json.tool $CONFIG_FILE >/dev/null 2>&1"
                    log "检测到JSON文件，使用python json工具检查"
                    ;;
                "xml")
                    SYNTAX_CHECK_CMD="xmllint --noout $CONFIG_FILE 2>&1"
                    log "检测到XML文件，使用xmllint进行语法检查"
                    ;;
                *)
                    log "警告: 无法确定文件类型，使用默认检查"
                    SYNTAX_CHECK_CMD="true"  # 默认不进行语法检查
                    ;;
            esac
            ;;
    esac
}

# 检查配置文件语法
check_syntax() {
    log "检查配置文件语法: $CONFIG_FILE"
    
    if [ -z "$SYNTAX_CHECK_CMD" ]; then
        determine_check_command
    fi
    
    # 执行语法检查
    local check_output=$(eval "$SYNTAX_CHECK_CMD")
    local exit_code=$?
    
    if [ $exit_code -eq 0 ]; then
        log "配置文件语法检查通过"
        return 0
    else
        log "配置文件语法错误: $check_output"
        echo "配置文件语法错误: $check_output"
        return 1
    fi
}

# 备份配置文件
backup_config() {
    # 确保备份目录存在
    mkdir -p "$BACKUP_DIR"
    
    # 创建带时间戳的备份
    local timestamp=$(date +'%Y%m%d_%H%M%S')
    local backup_file="${BACKUP_DIR}/$(basename "$CONFIG_FILE")_${timestamp}.bak"
    
    if cp "$CONFIG_FILE" "$backup_file"; then
        log "已备份配置文件到: $backup_file"
        
        # 清理旧备份
        local backups=($(ls -t "${BACKUP_DIR}/$(basename "$CONFIG_FILE")_"*.bak 2>/dev/null))
        if [ ${#backups[@]} -gt $MAX_BACKUP_COUNT ]; then
            for ((i=MAX_BACKUP_COUNT; i<${#backups[@]}; i++)); do
                rm -f "${backups[$i]}"
                log "已清理旧备份: ${backups[$i]}"
            done
        fi
        return 0
    else
        log "配置文件备份失败"
        echo "配置文件备份失败"
        return 1
    fi
}

# 修复配置文件语法错误
fix_syntax_errors() {
    log "尝试修复配置文件语法错误"
    local file_ext=$(echo "$CONFIG_FILE" | awk -F. '{print $NF}')
    local file_name=$(basename "$CONFIG_FILE")
    local fixed=0
    
    # 根据文件类型执行不同的修复策略
    case "$file_name" in
        "my.cnf"|"mysql.cnf")
            # 修复MySQL配置文件常见错误
            # 移除无效参数
            sed -i '/^query_cache_size/d' "$CONFIG_FILE"
            sed -i '/^query_cache_type/d' "$CONFIG_FILE"
            # 修复常见的语法错误
            sed -i 's/ = /=/' "$CONFIG_FILE"  # 移除等号两边的空格
            sed -i '/^[^#]*[^= ]*$/d' "$CONFIG_FILE"  # 移除没有等号的行
            fixed=1
            ;;
        "nginx.conf")
            # 修复Nginx常见错误
            sed -i 's/;$/;/' "$CONFIG_FILE"  # 确保分号结尾
            sed -i '/^[^#]*{[^}]*$/d' "$CONFIG_FILE"  # 移除不完整的块
            fixed=1
            ;;
        *)
            case "$file_ext" in
                "json")
                    # JSON格式修复（简单修复）
                    sed -i 's/，/,/g' "$CONFIG_FILE"  # 替换中文逗号
                    sed -i 's/：/:/g' "$CONFIG_FILE"  # 替换中文冒号
                    sed -i '$s/,$//' "$CONFIG_FILE"  # 移除最后一个元素的逗号
                    fixed=1
                    ;;
                "xml")
                    # XML格式修复（简单修复）
                    sed -i 's/&/\&amp;/g' "$CONFIG_FILE"  # 转义&符号
                    fixed=1
                    ;;
                "conf")
                    # 通用配置文件修复
                    sed -i 's/，/,/g' "$CONFIG_FILE"  # 替换中文逗号
                    sed -i '/^[[:space:]]*#/! s/[[:space:]]*#.*/#/' "$CONFIG_FILE"  # 修复注释位置
                    fixed=1
                    ;;
            esac
            ;;
    esac
    
    if [ $fixed -eq 1 ]; then
        log "已尝试自动修复配置文件错误"
        return 0
    else
        log "不支持的文件类型，无法自动修复"
        echo "不支持的文件类型，无法自动修复"
        return 1
    fi
}

# 主逻辑
main() {
    log "开始配置文件语法检查与修复: $CONFIG_FILE"
    
    # 检查文件是否存在
    if ! check_file_exists; then
        exit 1
    fi
    
    # 检查语法
    if check_syntax; then
        echo "配置文件语法正常"
        exit 0
    fi
    
    # 备份配置文件
    if ! backup_config; then
        exit 1
    fi
    
    # 尝试修复错误
    if fix_syntax_errors; then
        # 再次检查语法
        if check_syntax; then
            log "配置文件语法错误修复成功"
            echo "配置文件语法错误修复成功"
            exit 0
        else
            log "自动修复未能解决所有语法错误"
            echo "自动修复未能解决所有语法错误"
            exit 1
        fi
    else
        log "修复失败"
        echo "修复失败"
        exit 1
    fi
}

# 执行主逻辑
main
    